Skip to content

feat(terraform): implement App of Apps bootstrap for local/prod and migrate Tekton image builds to Buildah#81

Open
PhuocHoan wants to merge 7 commits into
mainfrom
users/hph/implement-terraform
Open

feat(terraform): implement App of Apps bootstrap for local/prod and migrate Tekton image builds to Buildah#81
PhuocHoan wants to merge 7 commits into
mainfrom
users/hph/implement-terraform

Conversation

@PhuocHoan
Copy link
Copy Markdown
Collaborator

@PhuocHoan PhuocHoan commented May 29, 2026

Description

This PR resolves issue #72 by implementing Terraform-based platform bootstrapping with App of Apps GitOps wiring for local-dev and prod environments. In addition, it integrates automated PipelineRun lifecycle management (pruning/cancellation), conditional database support in template scaffolding, custom Backstage extensions, NestJS security hardening, and structural refactoring to satisfy linter constraints.


Branch Scope (6 Commits)

  • 0119292 refactor(operator,portal): resolve CI/CD failures and linter warnings
  • 90ee9ed feat: monitor PipelineRuns and implement automated pruning and cancellation logic for concurrent executions
  • 18e8015 feat: add conditional database support to templates and implement UniqueNamePicker scaffolder extension
  • c5220b7 refactor: update NestJS template security, enhance CUE deployment definitions, and optimize Tekton pipeline and controller logic
  • 8f12464 feat: migrate Tekton builds to Buildah and refresh tooling
  • a3b52bf feat: implement terraform, database template fixes, and port-forward alerts

What Changed

1) Terraform & App of Apps Bootstrapping (Issue #72 Core)

  • Environments Stack: Added Terraform configurations for local-dev (k3d-oriented, low resource footprint) and prod (high-availability).
  • Modules Added: cluster-k3d, platform-services (ArgoCD + Tekton), gitea, and git-auth.
  • GitOps Wiring: Connected ArgoCD's App of Apps repository to helios-system-gitops with environment-specific paths.
  • Secrets Management: Provisioned credentials for ArgoCD repositories, git operations, Docker registries (Buildah), and Gitea API tokens.

2) PipelineRun Monitoring & Lifecycle Management (Tekton Controller)

  • Resource Monitoring: Configured the operator to watch PipelineRun events and map changes back to the main HeliosApp reconciliation requests.
  • Automated Pruning: Added pruning logic in the Tekton controller to keep only the 3 most recent PipelineRuns.
  • Concurrent Cancellation: Implemented active cancellation of older running/active PipelineRuns when a newer run is triggered, preventing out-of-order deployments and concurrent conflicts.
  • Webhook Fallback: Enabled fallback triggering of initial builds if a gitea-push webhook does not generate a PipelineRun immediately.

3) Custom Backstage Extension & Conditional Database Scaffolding

  • UniqueNamePicker Extension: Created a Backstage scaffolder field extension that checks name uniqueness against the Catalog API and enforces lowercase alphanumeric/hyphen formatting.
  • Conditional Templates: Updated .NET and NestJS templates to support conditional database provisioning (Prisma schemas, environment configurations, and Docker Compose wiring).

4) Buildah Migration & Deployment Hardening

  • Buildah Migration: Replaced Kaniko tasks with Buildah task definitions for building Docker images.
  • NestJS Security: Improved template security with stricter Docker configs.
  • CUE Engine Deduping: Deduplicated CUE rendering logic, and updated standard base specs for Kubernetes deployments.

5) Formatting, Tooling, & Linting Fixes

  • Linter Cleanup: Addressed revive prefix warnings on operator structs and interfaces (e.g., cue.CueEngine -> cue.Engine).
  • Prettier & Code Style: Resolved linter/formatting errors in portal components.
  • Taskfile/Scripts: Updated local-dev helpers, preflight checks, and port-forward alerts.

Acceptance Criteria Mapping for #72

  • Terraform bootstraps core platform services: Successfully implemented via environment stacks and modules.
  • local-dev uses k3d & dev settings: Handled in local-dev TF module.
  • ArgoCD syncs from helios-system-gitops: Implemented via App of Apps integration.
  • Basic secret provisioning flow: Standardized via Terraform and credentials setup scripts.

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update

Checklist

  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation
  • I have added evidence that prove my fix is effective or that my feature works
  • I have added unit tests for new feature
  • Existing unit tests pass locally with my changes
  • Prettier and linting checks pass (Backstage)
  • Issues linked to this Pull Request (Development section on the right)

Evidence:

screencapture-127-0-0-1-3030-2026-05-31-13_33_56 screencapture-127-0-0-1-3030-helios-dotnet-2026-05-31-13_35_04 screencapture-127-0-0-1-3030-helios-nestjs-2026-05-31-13_34_37 screencapture-127-0-0-1-3030-helios-platform-dotnet-2026-05-31-13_35_18 screencapture-127-0-0-1-3030-helios-platform-nestjs-2026-05-31-13_34_19 screencapture-localhost-3000-catalog-default-component-dotnet-argo-cd-2026-05-31-13_24_48 screencapture-localhost-3000-catalog-default-component-dotnet-database-2026-05-31-13_25_43 screencapture-localhost-3000-catalog-default-component-dotnet-kubernetes-2026-05-31-13_25_26 screencapture-localhost-3000-catalog-default-component-nestjs1-argo-cd-2026-05-31-13_31_17 screencapture-localhost-3000-catalog-default-component-nestjs1-kubernetes-2026-05-31-13_32_26 screencapture-localhost-3000-catalog-default-component-nestjs-argo-cd-2026-05-31-13_28_41 screencapture-localhost-3000-catalog-default-component-nestjs-database-2026-05-31-13_29_52 screencapture-localhost-3000-catalog-default-component-nestjs-kubernetes-2026-05-31-13_29_30 Screenshot From 2026-05-31 13-24-15 Screenshot From 2026-05-31 13-24-43 Screenshot From 2026-05-31 13-27-52 Screenshot From 2026-05-31 13-28-34 Screenshot From 2026-05-31 13-30-39 Screenshot From 2026-05-31 13-31-03 Screenshot From 2026-05-31 13-32-46 Screenshot From 2026-05-31 13-33-07 Screenshot From 2026-05-31 13-33-12 Screenshot From 2026-05-31 13-33-17 Screenshot From 2026-05-31 13-33-25 Screenshot From 2026-05-31 13-33-29 Screenshot From 2026-05-31 13-34-08 Screenshot From 2026-05-31 13-38-41

Summary by CodeRabbit

Release Notes

  • New Features

    • Added support for optional databases in application templates with conditional configuration
    • Implemented UniqueNamePicker field extension for Backstage scaffolder to validate unique application names
    • Enhanced database environment variable injection with init containers for database health checks
  • Infrastructure & Tooling

    • Migrated container image building from Kaniko to Buildah for improved rootless operation
    • Updated Kubernetes cluster tooling from Kind to K3d for local development
    • Added Terraform modules for local development infrastructure (cluster, platform services, Gitea integration)
  • Dependencies & Versions

    • Updated PostgreSQL to version 18.4 across all components
    • Upgraded Backstage and related packages to latest versions
    • Updated Node.js, Go, TypeScript, and build tools to current stable releases
    • Bumped Yarn to 4.15.0 and various npm package dependencies
  • Improvements

    • Enhanced logging and validation for database connectivity
    • Added retry logic for Prisma database connections
    • Improved ArgoCD configuration with high-availability support for production

PhuocHoan added 2 commits May 27, 2026 15:13
- replace Kaniko task wiring with Buildah-based pipeline params and npm cache workspace support
- add gitea-push initial PipelineRun fallback and update Tekton/controller reconciliation
- refresh local-dev, templates, docs, scripts, and dependency/tooling configs
Copilot AI review requested due to automatic review settings May 29, 2026 10:57
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

Review Change Stack

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: d0eec33c-b6db-49e0-9e8c-d5a8796e6661

📥 Commits

Reviewing files that changed from the base of the PR and between 8278027 and 3ea94df.

⛔ Files ignored due to path filters (6)
  • apps/operator/go.sum is excluded by !**/*.sum
  • apps/portal/.yarn/patches/@backstage-plugin-scaffolder-backend-module-gitea-npm-0.2.21-ac8e102ebc.patch is excluded by !**/.yarn/**
  • apps/portal/.yarn/releases/yarn-4.15.0.cjs is excluded by !**/.yarn/**
  • apps/portal/.yarn/releases/yarn-4.4.1.cjs is excluded by !**/.yarn/**
  • apps/portal/examples/nestjs-prisma-template/content/source/package-lock.json is excluded by !**/package-lock.json
  • apps/portal/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (149)
  • .github/workflows/operator-ci.yml
  • .github/workflows/portal-ci.yml
  • .gitignore
  • Taskfile.yml
  • apps/operator/.github/workflows/lint.yml
  • apps/operator/.github/workflows/test-e2e.yml
  • apps/operator/.github/workflows/test.yml
  • apps/operator/.golangci.yml
  • apps/operator/AUTOMATION_GUIDE.md
  • apps/operator/Makefile
  • apps/operator/README.md
  • apps/operator/api/v1alpha1/groupversion_info.go
  • apps/operator/api/v1alpha1/heliosapp_types.go
  • apps/operator/cmd/main.go
  • apps/operator/config/crd/bases/app.helios.io_heliosapps.yaml
  • apps/operator/config/manager/kustomization.yaml
  • apps/operator/go.mod
  • apps/operator/internal/controller/argocd/application.go
  • apps/operator/internal/controller/argocd/application_test.go
  • apps/operator/internal/controller/database/credentials.go
  • apps/operator/internal/controller/database/injection.go
  • apps/operator/internal/controller/database/reconciler.go
  • apps/operator/internal/controller/database/reconciler_test.go
  • apps/operator/internal/controller/database/resources.go
  • apps/operator/internal/controller/database/resources_test.go
  • apps/operator/internal/controller/database/traits.go
  • apps/operator/internal/controller/gitopssync/reconciler.go
  • apps/operator/internal/controller/heliosapp_controller.go
  • apps/operator/internal/controller/heliosapp_controller_test.go
  • apps/operator/internal/controller/heliosapp_controller_unit_test.go
  • apps/operator/internal/controller/shared/gitea_url.go
  • apps/operator/internal/controller/tekton/pipelinerun.go
  • apps/operator/internal/controller/tekton/reconciler.go
  • apps/operator/internal/cue/e2e_validation_test.go
  • apps/operator/internal/cue/engine.go
  • apps/operator/internal/cue/engine_test.go
  • apps/operator/internal/cue/tekton.go
  • apps/operator/internal/cue/tekton_test.go
  • apps/operator/internal/gitops/gitops.go
  • apps/operator/internal/gitops/gitops_test.go
  • apps/operator/tekton/pipeline.yaml
  • apps/operator/test/e2e/e2e_suite_test.go
  • apps/operator/test/e2e/e2e_test.go
  • apps/operator/test/utils/utils.go
  • apps/portal/.gitignore
  • apps/portal/.yarnrc.yml
  • apps/portal/app-config.yaml
  • apps/portal/backstage.json
  • apps/portal/examples/advanced-template/template.yaml
  • apps/portal/examples/dotnet-template/content/README.md
  • apps/portal/examples/dotnet-template/content/gitops/helios-app.yaml
  • apps/portal/examples/dotnet-template/content/source/.env.example
  • apps/portal/examples/dotnet-template/content/source/Dockerfile
  • apps/portal/examples/dotnet-template/content/source/Program.cs
  • apps/portal/examples/dotnet-template/content/source/README.md
  • apps/portal/examples/dotnet-template/content/source/appsettings.json
  • apps/portal/examples/dotnet-template/content/source/docker-compose.yml
  • apps/portal/examples/dotnet-template/content/source/global.json
  • apps/portal/examples/dotnet-template/template.yaml
  • apps/portal/examples/nestjs-prisma-template/content/gitops/helios-app.yaml
  • apps/portal/examples/nestjs-prisma-template/content/source-db/prisma.config.ts
  • apps/portal/examples/nestjs-prisma-template/content/source-db/prisma/migrations/migration_lock.toml
  • apps/portal/examples/nestjs-prisma-template/content/source-db/prisma/schema.prisma
  • apps/portal/examples/nestjs-prisma-template/content/source-db/src/prisma/prisma.module.ts
  • apps/portal/examples/nestjs-prisma-template/content/source-db/src/prisma/prisma.service.ts
  • apps/portal/examples/nestjs-prisma-template/content/source/.dockerignore
  • apps/portal/examples/nestjs-prisma-template/content/source/.env.example
  • apps/portal/examples/nestjs-prisma-template/content/source/Dockerfile
  • apps/portal/examples/nestjs-prisma-template/content/source/README.md
  • apps/portal/examples/nestjs-prisma-template/content/source/package.json
  • apps/portal/examples/nestjs-prisma-template/content/source/src/app.module.ts
  • apps/portal/examples/nestjs-prisma-template/content/source/src/app.service.ts
  • apps/portal/examples/nestjs-prisma-template/content/source/tsconfig.json
  • apps/portal/examples/nestjs-prisma-template/template.yaml
  • apps/portal/examples/postgrest-template/template.yaml
  • apps/portal/examples/spring-boot-template/content/source/Dockerfile
  • apps/portal/examples/spring-boot-template/content/source/docker-compose.yml
  • apps/portal/examples/spring-boot-template/template.yaml
  • apps/portal/package.json
  • apps/portal/packages/app/e2e-tests/app.test.ts
  • apps/portal/packages/app/package.json
  • apps/portal/packages/app/public/index.html
  • apps/portal/packages/app/src/App.tsx
  • apps/portal/packages/app/src/apis.ts
  • apps/portal/packages/app/src/components/Root/LogoFull.tsx
  • apps/portal/packages/app/src/components/Root/LogoIcon.tsx
  • apps/portal/packages/app/src/components/database/DatabaseTab.tsx
  • apps/portal/packages/app/src/scaffolder/DatabasePickerExtension/DatabasePicker.tsx
  • apps/portal/packages/app/src/scaffolder/UniqueNamePickerExtension/UniqueNamePicker.tsx
  • apps/portal/packages/app/src/scaffolder/UniqueNamePickerExtension/extension.ts
  • apps/portal/packages/app/src/scaffolder/UniqueNamePickerExtension/index.ts
  • apps/portal/packages/app/src/scaffolder/index.ts
  • apps/portal/packages/app/src/themes/heliosThemes.ts
  • apps/portal/packages/backend/package.json
  • apps/portal/packages/backend/src/extensions/database-router-simple.ts
  • apps/portal/plugins/helios-backend/README.md
  • apps/portal/plugins/helios-backend/package.json
  • apps/portal/plugins/helios-backend/src/plugin.ts
  • apps/portal/plugins/helios-backend/src/router.ts
  • apps/portal/plugins/helios-backend/tsconfig.json
  • apps/portal/start-dev.sh
  • apps/portal/tsconfig.json
  • cue/cue.mod/module.cue
  • cue/definitions/bases/deployment.cue
  • cue/definitions/bases/service.cue
  • cue/definitions/components/web-service.cue
  • cue/definitions/tekton/common.cue
  • cue/definitions/tekton/pipelines/patterns.cue
  • cue/definitions/tekton/schema.cue
  • cue/definitions/tekton/tasks/buildah-build.cue
  • cue/definitions/tekton/tasks/git-clone.cue
  • cue/definitions/tekton/tasks/git-update.cue
  • cue/definitions/tekton/tasks/kaniko-build.cue
  • cue/definitions/tekton/tasks/postgrest-reload.cue
  • cue/definitions/tekton/tasks/registry.cue
  • cue/definitions/tekton/triggers/github-push.cue
  • cue/engine/builder.cue
  • cue/engine/tekton_builder.cue
  • docs/APP_STARTUP_GUIDE.md
  • docs/ARCHITECTURE.md
  • docs/design/tekton-cue-mapping-design.md
  • docs/design/tekton-cue-task-breakdown.md
  • infrastructure/environments/local-dev/.terraform.lock.hcl
  • infrastructure/environments/local-dev/main.tf
  • infrastructure/environments/local-dev/providers.tf
  • infrastructure/environments/local-dev/terraform.tfvars
  • infrastructure/environments/local-dev/variables.tf
  • infrastructure/environments/prod/.terraform.lock.hcl
  • infrastructure/environments/prod/main.tf
  • infrastructure/environments/prod/providers.tf
  • infrastructure/environments/prod/variables.tf
  • infrastructure/modules/cluster-k3d/main.tf
  • infrastructure/modules/cluster-k3d/registries.yaml.tpl
  • infrastructure/modules/cluster-k3d/variables.tf
  • infrastructure/modules/cluster-k3d/versions.tf
  • infrastructure/modules/git-auth/main.tf
  • infrastructure/modules/git-auth/variables.tf
  • infrastructure/modules/git-auth/versions.tf
  • infrastructure/modules/gitea/main.tf
  • infrastructure/modules/gitea/variables.tf
  • infrastructure/modules/gitea/versions.tf
  • infrastructure/modules/platform-services/argocd.tf
  • infrastructure/modules/platform-services/tekton.tf
  • infrastructure/modules/platform-services/variables.tf
  • infrastructure/modules/platform-services/versions.tf
  • scripts/check-prereqs.bat
  • scripts/check-prereqs.sh
  • scripts/setup-credentials.ps1
  • scripts/start-portal.ps1
 _______________________________________________________________________________________
< If you don't fail at least 90% of the time, you're not aiming high enough. - Alan Kay >
 ---------------------------------------------------------------------------------------
  \
   \   (\__/)
       (•ㅅ•)
       /   づ
📝 Walkthrough

Walkthrough

PR đồng bộ hệ thống: chuyển Tekton sang Buildah với tham số kebab-case, refactor Operator (CUE/GitOps/API/types), nâng Postgres 18.4, cập nhật Portal/Backstage/templates, thêm Terraform cho local-dev/prod (k3d, ArgoCD, Tekton, Gitea), cùng cập nhật CI và script.

Changes

Hệ thống Buildah + Operator + Portal + Terraform

Layer / File(s) Summary
Buildah pipeline, Operator refactor, Portal/templates, Terraform infra
apps/operator/..., apps/portal/..., cue/..., infrastructure/..., .github/workflows/*, Taskfile.yml, scripts/*, docs/*
Chuyển Tekton sang Buildah và tham số kebab-case; refactor Engine/GitOps/Controller; cập nhật Postgres 18.4; thêm field build customization; mở rộng CUE builder (DB env/initContainers); cập nhật Portal/Backstage và templates; bổ sung Terraform modules cho k3d/ArgoCD/Tekton/Gitea ở local-dev/prod; điều chỉnh CI và scripts.

Sequence Diagram(s)

(n/a)

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Suggested reviewers

  • hoangphuc841
  • nghiaz160904
  • PhamHoangKha1403
  • VH3956

Poem

Tai thỏ quệt mực, vẽ Buildah bay,
Tekton ràng tham số, chữ-kebab xếp ngay.
Operator hòa nhịp, GitOps đẩy tay,
Portal reo sáng, Mission Control bày.
Terraform gieo mầm, k3d nảy cây—
Helios rực rỡ, đêm thành ngày! 🌕🐇✨

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch users/hph/implement-terraform

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

PhuocHoan added 4 commits May 30, 2026 09:51
…initions, and optimize Tekton pipeline and controller logic
Fix Prettier formatting in portal components, deduplicate CUE engine render logic, resolve revive package prefix warnings on interfaces/structs, replace deprecated runtime scheme builder, and fix slice preallocation warning in Tekton controller.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 35

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
apps/operator/internal/controller/heliosapp_controller.go (1)

228-249: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Thiếu RBAC cho watch PipelineRun.

Block này thêm watcher cho tekton.dev/v1 PipelineRun, nhưng file chưa bổ sung kubebuilder RBAC cho pipelineruns với quyền get;list;watch. Khi chạy trong cluster, informer mới sẽ không đọc được PipelineRun và trigger reconcile này sẽ lỗi quyền.

🛠️ Gợi ý bổ sung
 // +kubebuilder:rbac:groups=argoproj.io,resources=applications,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups=tekton.dev,resources=pipelineruns,verbs=get;list;watch
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/operator/internal/controller/heliosapp_controller.go` around lines 228 -
249, The SetupWithManager adds a watcher for tekton.dev/v1 PipelineRun (see pr
variable and r.findObjectsForPipelineRun) but there is no kubebuilder RBAC
granting get,list,watch on pipelineruns; add a kubebuilder RBAC comment for the
PipelineRun resource with verbs=get;list;watch (matching Group=tekton.dev
Version=v1 Resource=pipelineruns) so the controller pod can inform and reconcile
PipelineRun events referenced by SetupWithManager/ findObjectsForPipelineRun.
Taskfile.yml (1)

593-600: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Đừng ghi đè toàn bộ imagePullSecrets của default ServiceAccount.

Patch này thay cả mảng imagePullSecrets, nên mọi secret pull có sẵn trên sa/default sẽ biến mất. Cách an toàn hơn là append nếu chưa tồn tại, hoặc apply một manifest hợp nhất thay vì replace nguyên danh sách.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Taskfile.yml` around lines 593 - 600, The current patch command overwrites
the default ServiceAccount's imagePullSecrets array; change the logic that
targets the 'default' ServiceAccount so it appends the docker-credentials entry
only if missing instead of replacing the whole array. Locate the kubectl patch
for "sa default" in the Taskfile.yml and replace the destructive patch with a
safe check-and-append approach (e.g., use a JSON patch via kubectl --type=json
that conditionally adds the {"name":"docker-credentials"} entry if not present,
or fetch the SA, inspect imagePullSecrets and patch/merge back only when needed)
so existing imagePullSecrets are preserved. Ensure the same non-destructive
behavior is applied consistently alongside the existing 'pipeline'
ServiceAccount handling.
cue/definitions/tekton/pipelines/patterns.cue (1)

247-256: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Đồng bộ tên param replicas/port với task git-update-manifest.

Task ở cue/definitions/tekton/tasks/git-update.cue đã đổi schema sang lowercase, nhưng Line 255 và Line 256 vẫn truyền REPLICAS/PORT. Tekton sẽ bỏ qua hai override này và task rơi về default 2/8080, nên manifest GitOps có thể bị render sai cổng hoặc số replica.

🛠️ Gợi ý sửa
-			{name: "REPLICAS", value:                             "$(params.\(`#PipelineParams.replicas.name`))"},
-			{name: "PORT", value:                                 "$(params.\(`#PipelineParams.port.name`))"},
+			{name: "replicas", value:                             "$(params.\(`#PipelineParams.replicas.name`))"},
+			{name: "port", value:                                 "$(params.\(`#PipelineParams.port.name`))"},
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cue/definitions/tekton/pipelines/patterns.cue` around lines 247 - 256, The
params array in patterns.cue uses uppercase names "REPLICAS" and "PORT" which
don't match the lowered param names used by the git-update-manifest task (see
git-update.cue); replace the two entries with name: "replicas" and name: "port"
(or whatever exact lowercase identifiers the task defines) so the overrides from
patterns.cue apply to the git-update-manifest task results and prevent falling
back to defaults 2/8080.
apps/operator/internal/controller/tekton/pipelinerun.go (1)

44-57: ⚠️ Potential issue | 🟠 Major

Thống nhất Tekton API version giữa tạo và list PipelineRun

  • apps/operator/internal/controller/tekton/pipelinerun.go tạo PipelineRun với apiVersion: tekton.dev/v1beta1.
  • apps/operator/internal/controller/tekton/reconciler.go lại List PipelineRunList bằng schema.GroupVersionKind{Group:"tekton.dev", Version:"v1"} trong PrunePipelineRuns/CancelOlderPipelineRuns → có thể khiến prune/cancel không tác động đúng nếu cluster không serve/convert tekton.dev/v1.
  • Phần đổi tên params sang kebab-case (gitops-repo-url, manifest-path, gitops-secret-ref, context-subpath, …) đã khớp với #CommonParams trong cue/definitions/tekton/common.cueapps/operator/tekton/pipeline.yaml nên không cần cập nhật đồng bộ thêm ở luồng này.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/operator/internal/controller/tekton/pipelinerun.go` around lines 44 -
57, PipelineRun creation uses apiVersion "tekton.dev/v1beta1" in pipelinerun.go
but the reconciler (PrunePipelineRuns/CancelOlderPipelineRuns in reconciler.go)
lists PipelineRunList with schema.GroupVersionKind{Group:"tekton.dev",
Version:"v1"}, causing a mismatch; update the GroupVersionKind used when listing
PipelineRunList to Version:"v1beta1" (or otherwise make both sides use the same
Tekton API version) so prune/cancel operate on the same resource version as
created.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/operator-ci.yml:
- Line 37: The workflow uses an unpinned action reference "uses:
golangci/golangci-lint-action@v9" which should be pinned to a commit SHA to
mitigate supply-chain risk; update that line to the corresponding commit SHA for
golangci/golangci-lint-action and similarly pin other actions used in this file
(e.g., "checkout@v6" and "setup-go@v6") to their commit SHAs so all action
references are consistent and immutable.

In `@apps/operator/.github/workflows/test-e2e.yml`:
- Line 25: Thay vì tải script cài đặt k3d từ nhánh main, sửa bước chạy curl để
ghim một tag phát hành cố định (ví dụ thiết lập TAG=vX.Y.Z và dùng
https://raw.githubusercontent.com/k3d-io/k3d/$TAG/install.sh) và chạy script đã
ghim, đảm bảo hành vi lặp lại; cập nhật dòng hiện tại chứa "curl -s
https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash" để sử dụng
biến TAG hoặc hằng số tag và (tùy chọn) thêm kiểm tra checksum/signature trước
khi pipe vào bash.

In `@apps/operator/.golangci.yml`:
- Around line 38-40: Don't disable SA1019 globally; instead restrict the
suppression to the specific package/files or lines that legitimately require
using a deprecated API. Update the .golangci.yml by removing the global SA1019
entry under linters/staticcheck and add an exclude-rules block that targets only
the specific path(s) or file patterns and the linter name "staticcheck" with
text "SA1019" (or use per-file inline //nolint:staticcheck when narrowest scope
is needed), so other code still receives SA1019 warnings.

In `@apps/operator/internal/controller/database/reconciler_test.go`:
- Line 348: Trình biên dịch báo lỗi vì dùng new(int32(1)) (đối số của new phải
là kiểu, không phải giá trị); sửa tất cả chỗ sử dụng này (ví dụ trường Replicas
trong resources.go và reconciler_test.go) bằng cách khởi tạo một biến kiểu int32
với giá trị 1 rồi trả về địa chỉ của biến đó (ví dụ: tạo biến v := int32(1) và
trả về &v trong biểu thức khởi tạo), hoặc dùng helper trả về *int32 nếu dự án
có; cập nhật mọi vị trí dùng new(int32(1)) thành mẫu khởi tạo
biến-and-return-address tương tự.

In `@apps/operator/internal/controller/tekton/reconciler.go`:
- Around line 224-228: The comparator passed to sort.Slice is taking metav1.Time
values and incorrectly using new(...) which doesn't compile; fix the comparator
in the sort.Slice call by comparing the underlying time.Time values (e.g. use
prList.Items[i].GetCreationTimestamp().Time.Before(prList.Items[j].GetCreationTimestamp().Time))
or by taking addresses of named metav1.Time variables (jTime :=
prList.Items[j].GetCreationTimestamp(); iTime :=
prList.Items[i].GetCreationTimestamp(); return iTime.Before(&jTime)); update the
comparator in the sort.Slice (the anonymous func used to sort prList.Items)
accordingly.

In `@apps/operator/internal/cue/tekton.go`:
- Line 1: Dòng comment đầu tiên `// Package cue /*` chứa ký tự dư `/*` và gây
lỗi định dạng; thay thế comment đó bằng một doc-comment chuẩn trước khai báo
package (ví dụ bắt đầu bằng `// Package cue ...`) mà không có `/*` để tạo
comment mô tả gói cue; đảm bảo comment đứng ngay trước khai báo `package cue` và
chỉ là một dòng hoặc block comment Go hợp lệ.

In `@apps/operator/Makefile`:
- Line 165: Dòng hiện tại thu pids từ lsof (-ti :8081) và gọi kill -9 trực tiếp,
có thể giết nhầm tiến trình và không cho tiến trình dọn tài nguyên; thay bằng
gửi SIGTERM trước (kill -15 hoặc kill $$pids), chờ trong vòng lặp ngắn để kiểm
tra lại pids và chỉ dùng kill -9 nếu tiến trình vẫn còn; cập nhật logic quanh
biến pids, lsof -ti :8081 và lệnh kill để phản ánh thứ tự: TERM -> chờ/kiểm tra
-> KILL nếu cần, và thêm echo thông báo tương ứng.
- Around line 136-138: The test-e2e Makefile target currently runs "go test"
then "$(MAKE) cleanup-test-e2e", but if the test command fails the cleanup step
is skipped; change the target to run the test inside a shell that sets a trap to
always invoke the existing cleanup target (e.g., use: sh -c 'trap "$(MAKE)
cleanup-test-e2e" EXIT; K3D_CLUSTER=$(K3D_CLUSTER) go test ./test/e2e/ -v
-ginkgo.v' ), ensuring the cleanup-test-e2e target always executes regardless of
go test exit status while keeping the K3D_CLUSTER variable passed through.

In `@apps/operator/README.md`:
- Line 26: Update the README description for the make target "make test-e2e" to
accurately reflect its behavior: change the sentence that currently says it
"installs k3d if needed" to state that it checks for k3d and fails with an error
if k3d is not installed (or instructs the user to install k3d), so the README
matches the Makefile's actual behavior for the make test-e2e target.

In `@apps/operator/tekton/pipeline.yaml`:
- Around line 29-32: The parameters env-vars and resources declared in the
pipeline parameters are unused (dead parameters); either remove them from the
parameters list or wire them into the downstream tasks that need
them—specifically check the update-gitops-manifest task (taskRef:
git-update-manifest) and any other tasks/steps that should receive env-vars and
resources (via params or taskRun/step env/resource fields) and add the
corresponding param entries and references, or delete the env-vars and resources
parameter definitions from the pipeline YAML if no task consumes them.

In `@apps/portal/.yarnrc.yml`:
- Around line 1-10: The current Yarn config is insecure:
approvedGitRepositories: '**' is too permissive, enableScripts: true allows
third-party lifecycle scripts, and npmMinimalAgeGate: 0 disables the minimum age
gate; update .yarnrc.yml by replacing approvedGitRepositories with a tight
allowlist (specific domains, orgs or repo patterns) instead of '**', set
enableScripts to false (or scope it only where explicitly required), and set
npmMinimalAgeGate to a positive duration (e.g., '1d' or larger) to reinstate the
publish age gate; keep other keys (nodeLinker, yarnPath) unchanged unless you
have a reason to modify them.

In `@apps/portal/examples/nestjs-prisma-template/content/source/tsconfig.json`:
- Line 18: The tsconfig template currently forces "stableTypeOrdering": true
which is a diagnostic/transition flag (TS 6→7) and can significantly slow
type-checking; remove this fixed setting from the template (or default it to
false / make it configurable) so new projects aren't penalized—locate the
"stableTypeOrdering" entry in the tsconfig.json and delete the key (or set it to
false / document it as an opt-in) so the template no longer hard-enables this
flag.

In `@apps/portal/examples/spring-boot-template/template.yaml`:
- Around line 79-80: Update the explanatory comment that currently says "Use
repoName as the app identifier" to reflect that the template now uses the
parameters.name value as the app identifier (i.e., mention parameters.name
instead of repoName) so the comment matches the actual value used in the name:
${{ parameters.name }}; locate the comment adjacent to the name: ${{
parameters.name }} line and replace the outdated reference to repoName with a
brief note about using parameters.name (and that it is Kubernetes/URL safe) to
avoid confusion.

In
`@apps/portal/packages/app/src/scaffolder/UniqueNamePickerExtension/extension.ts`:
- Around line 20-24: The current validation uses a regex that allows leading or
trailing hyphens; in the block that checks the variable "value" and calls
validation.addError, replace the existing pattern with one that requires the
first and last character to be a lowercase letter or digit while allowing
hyphens only internally (i.e., no leading or trailing '-' ), preserving the
lowercase/alphanumeric-only rule and the same validation.addError message.

In `@apps/portal/plugins/helios-backend/src/plugin.ts`:
- Around line 23-27: The code is using a blunt cast "(await createRouter({
logger, config })) as any" when calling httpRouter.use, which hides type
mismatches between your createRouter return and Backstage/Express
router/middleware signature; update the createRouter function's return type (and
any related helper types) so it explicitly returns the correct Express/Backstage
router/middleware type expected by httpRouter.use (e.g., express.Router or the
framework's RouterMiddleware type), or change the function to wrap/return a
correctly typed router instance, then remove the "as any" cast in plugin.ts (and
make the analogous fix in database-router-simple.ts) so the compiler enforces
the proper contract instead of silencing it.

In `@cue/definitions/tekton/pipelines/patterns.cue`:
- Around line 166-180: The script currently runs "npm ci" whenever package.json
exists, which fails if no lockfile is present; update the logic around the
existing checks (the if that tests for package-lock.json and package.json and
the "npm ci --ignore-scripts --no-audit --no-fund --progress=false
--fetch-retries=5 --fetch-retry-mintimeout=15000" invocation) so that you only
run "npm ci" when a lockfile exists (package-lock.json or npm-shrinkwrap.json);
if package.json exists but no lockfile, either run "npm install --no-audit
--no-fund --progress=false" instead or skip install—implement the preferred path
by replacing the current single "npm ci" call with a conditional: if [ -f
package-lock.json ] || [ -f npm-shrinkwrap.json ]; then npm ci ...; else npm
install ...; fi.

In `@cue/definitions/tekton/tasks/buildah-build.cue`:
- Around line 30-72: The Task BuildahBuild still runs Kaniko; update the steps
in the task (the steps array under BuildahBuild) to use Buildah commands instead
of Kaniko: replace the step that uses image
gcr.io/kaniko-project/executor:v1.23.2-debug and invocation of /kaniko/executor
with a Buildah image and a script that runs buildah bud (with --storage-driver
from params.storage-driver, --isolation from params.buildah-isolation, and
--platform from params.build-platforms (use only the first platform if a list)),
then run buildah push to $(params.image) and write the digest to
/tekton/results/IMAGE_DIGEST; also change the volume/secret mount for docker
auth from /kaniko/.docker to Buildah's auth location (/root/.docker) or use
buildah's --authfile flag tied to the secret (params.docker-secret), and ensure
the write-image-url step still reads /tekton/results/IMAGE_DIGEST into
results.IMAGE_URL.path so params.image@digest is emitted.

In `@cue/definitions/tekton/tasks/git-update.cue`:
- Around line 172-205: The script must not embed credentials into the remote URL
(avoid creating REPO_URL_WITH_AUTH and calling git_safe remote set-url origin);
instead keep origin as-is (RAW_URL handling can remain for validation) and
before pushing set an HTTP Basic auth header via git config --local
http.extraHeader using a Base64-encoded "username:password" value (compute the
Base64 string from ${username}:${password}), perform git_safe push origin
"$(params.gitops-repo-branch)" and then remove/clear the http.extraHeader to
avoid leaking credentials; replace references to REPO_URL_WITH_AUTH and the
git_safe remote set-url origin call with this header-based flow so pushes
authenticate without embedding credentials in the URL.

In `@cue/definitions/tekton/tasks/registry.cue`:
- Line 7: Bản đồ `"buildah-build"` trỏ tới `#BuildahBuild` nhưng nội dung
`#BuildahBuild` vẫn dùng executor/command của Kaniko (ví dụ
`gcr.io/kaniko-project/executor` và `/kaniko/executor`); sửa sao cho tên/nhãn và
hành vi nhất quán: hoặc thay toàn bộ image/command trong `#BuildahBuild` để dùng
Buildah (ví dụ đổi image sang một Buildah image như quay.io/buildah/stable và
thay các lệnh Kaniko bằng lệnh Buildah tương ứng như buildah bud/buildah push
hoặc script dùng buildah), hoặc nếu giữ Kaniko thì đổi tên task/nhãn/ghi chú để
phản ánh Kaniko; tìm và cập nhật mọi tham chiếu đến `#BuildahBuild`, chuỗi image
`gcr.io/kaniko-project/executor` và lệnh `/kaniko/executor` trong định nghĩa
task để đảm bảo nhất quán.

In `@cue/engine/builder.cue`:
- Around line 89-98: The env block currently injects Postgres-specific variables
(PGRST_DB_URI and DATABASE_URL using postgres://) unconditionally, causing wrong
connection strings for other dbType values; update the builder.cue env array so
that PGRST_DB_URI and the DATABASE_URL entry (which builds
postgres://$(DB_USER):$(DB_PASS)@$(DB_HOST):$(DB_PORT)/$(DB_NAME)) are only
added when dbType == "postgres" (use a conditional or separate concat branch
around those two entries referencing dbType and dbSecretName) while leaving the
generic DB_* entries unchanged.

In `@infrastructure/environments/local-dev/providers.tf`:
- Line 22: Replace the hardcoded config_path value in providers.tf (the
config_path setting) with a configurable value: add a new variable
"kubeconfig_path" in variables.tf (default "~/.kube/config") and reference
var.kubeconfig_path in providers.tf, and additionally support honoring the
KUBECONFIG environment variable by using that when set; also consider applying
pathexpand when evaluating the path so Windows/home-dir expansions work
correctly.
- Line 24: The Terraform config currently sets insecure = true (multiple
occurrences) which should be either documented or removed; update each insecure
= true occurrence to either be removed or replaced with a documented toggle
(e.g., a variable like var.skip_tls_validation with a clear comment) and add an
inline comment explaining why TLS verification is skipped for local k3d only and
instructions to switch to proper certs (or how to configure k3d to use
self-signed/valid certs); ensure the default remains secure (false) and that any
boolean toggle is clearly named and documented so this setting cannot be
accidentally promoted to production.

In `@infrastructure/environments/prod/providers.tf`:
- Line 2: The Terraform version constraint in providers.tf (required_version =
">= 1.15.5") is out of sync with the prereq checks in scripts/check-prereqs.sh
and .bat which only require 1.15; update one side so they match: either raise
the prereq minimum in scripts/check-prereqs.sh/.bat to 1.15.5, or change
providers.tf's required_version to a compatible range (e.g. ">= 1.15.0, <
1.16.0" or "~> 1.15.5") and document the chosen production version; locate the
check-prereqs scripts and the required_version line in providers.tf to make the
change.

In `@infrastructure/modules/cluster-k3d/main.tf`:
- Around line 1-4: The terraform_data "k3d_cluster" resource only triggers
replacement on var.cluster_name, so changes to the registry configuration
(var.registry_name, var.registry_port) won't recreate the cluster and k3d may
keep pointing to the old mirror; update the triggers_replace list on resource
"terraform_data" "k3d_cluster" to include the registry-related variables (e.g.,
var.registry_name and var.registry_port) so any change to those values forces
recreate, and verify any script or template that uses
registry_name/registry_port (the create script referenced by k3d_cluster) reads
the updated values.

In `@infrastructure/modules/git-auth/main.tf`:
- Around line 1-7: Trong resource gitlab_personal_access_token.this thay vì
hardcode expires_at = "2026-12-31" dùng module time của HashiCorp: tạo
time_static và time_offset và truyền giá trị đã format về "YYYY-MM-DD" (ví dụ
dùng formatdate("YYYY-MM-DD", time_offset.<name>.rfc3339)) cho thuộc tính
expires_at để có rolling expiry; đồng thời thu hẹp scopes từ ["api"] sang quyền
tối thiểu cần thiết (ví dụ "read_repository" hoặc "write_repository") để áp dụng
principle of least privilege cho token.

In `@infrastructure/modules/gitea/main.tf`:
- Around line 94-96: The use of uuid() inside the input map (the configure_gitea
input) causes every terraform plan to show a diff; remove the nondeterministic
uuid() and instead add a triggers_replace block on the resource (use
triggers_replace = { ... }) populated with the actual deterministic variables or
configuration flags that should force recreation (e.g., var.gitea_version,
var.repo_settings, var.admin_user, or a specific checksum of templates). This
keeps plans stable and only triggers reruns when the real inputs change.

In `@infrastructure/modules/gitea/variables.tf`:
- Around line 13-18: Biến Terraform gitea_admin_pass hiện có mật khẩu mặc định
"helios123" — hãy loại bỏ default cứng này và để biến bắt buộc (không khai báo
default) hoặc thay bằng cơ chế an toàn (ví dụ tạo bằng random_password và truyền
vào output/secret store); giữ sensitive = true và cập nhật description để chỉ rõ
cách cung cấp giá trị (via -var, tfvars, hoặc secret manager). Thao tác này liên
quan trực tiếp tới biến gitea_admin_pass trong file và đảm bảo không còn
credential hardcoded.

In `@infrastructure/modules/platform-services/argocd.tf`:
- Around line 78-80: Thay vì dùng targetRevision: HEAD, thay bằng biến để khóa
revision cụ thể; cập nhật cấu hình ứng dụng ArgoCD (tham chiếu targetRevision)
để dùng ví dụ biến var.gitops_repo_revision (hoặc tên biến tương ứng) và đảm bảo
biến này được khai báo/đặt giá trị trong các môi trường (local/prod) thay vì mặc
định HEAD, đồng thời giữ repo URL hiện tại var.gitops_repo_url; mục tiêu là pin
branch/tag/commit rõ ràng thay cho HEAD trong phần cấu hình targetRevision.

In `@infrastructure/modules/platform-services/tekton.tf`:
- Around line 160-168: The resource terraform_data.install_crds currently only
receives a static path via input.crd_dir so its provisioner won't re-run when
files change; update install_crds so Terraform observes CRD content changes by
feeding a content checksum into its inputs/triggers (e.g., compute a hash of all
files under ${var.workspace_root}/apps/operator/config/crd via a data/local_file
or external/local-exec checksum step and pass that checksum into
terraform_data.install_crds.input or into triggers/ triggers_replace), ensuring
the provisioner "local-exec" command is re-executed whenever any CRD file under
that directory changes.

In `@infrastructure/modules/platform-services/variables.tf`:
- Around line 48-52: The variable workspace_root currently says "Absolute path"
but its default "../../../" is relative; either update the variable description
to indicate it's a relative path (e.g., "Relative path to the workspace root
directory") or convert the default into a true absolute path and use that
throughout: compute an absolute path with abspath(path.module + "/../../../")
(or compute abspath(var.workspace_root) in a local like
local.workspace_root_abs) and replace usages with the absolute local; reference
variable workspace_root, builtins path.module and abspath, and consider adding
local.workspace_root_abs for downstream consumers.

In `@scripts/check-prereqs.bat`:
- Around line 38-41: The call that enforces `make` as required uses the required
check routine `:check_tool` which makes Windows fail hard; change the `call
:check_tool "make" "make --version"` invocation to use the optional routine
`:check_optional_tool` so `make` is treated as a warning (matching the behavior
of check-prereqs.sh). Locate the `call :check_tool "make" "make --version"` line
and replace it with `call :check_optional_tool "make" "make --version"` (leaving
the other `:check_tool` calls for operator-sdk, terraform, task unchanged).

In `@scripts/setup-credentials.ps1`:
- Around line 32-34: The kubectl patch command in the script (the block using
"Write-Host" and "kubectl patch sa default -p '{"imagePullSecrets": [{"name":
"docker-credentials"}]}'") does not specify a namespace and will operate against
the current kubectl context; update the patch command to include the namespace
flag (e.g., add -n default) so the default ServiceAccount in the intended
namespace is patched, and likewise update the earlier pipeline patch step that
patches the ServiceAccount to also include -n default to keep behavior
consistent.

In `@scripts/start-portal.ps1`:
- Line 37: Remove the sensitive Write-Host call that prints the ArgoCD admin
password (the line containing Write-Host "[ArgoCD] Admin Password: $pass") so
the secret is not emitted to console/logs; instead either omit any output or
replace it with a non-sensitive informational message (e.g., "ArgoCD admin
password generated — handle securely" or instructions on how to retrieve the
password manually) since the password is immediately used to generate a token
and should not be logged.

In `@Taskfile.yml`:
- Around line 123-179: The Taskfile's setup flow (setup:all -> setup:registry
and setup:terraform) assumes POSIX shells and currently skips setup:registry on
Windows (platforms: [linux, darwin]) which breaks bootstrap on Windows; update
Taskfile.yml so setup:all either branches by platform or fails fast with a clear
message. Concretely, modify setup:all to detect platform and: (a) call the
existing setup:registry and setup:terraform on linux/darwin, or (b) when on
Windows, print an explicit error and exit recommending WSL/Git Bash (or invoke
Windows-compatible equivalents) — touch the tasks named setup:all,
setup:registry and setup:terraform to add the platform-check/fail-fast logic and
messages so the bootstrap won't silently stop on native Windows shells.
- Around line 628-666: The dev:portal task currently always invokes
dev:free-ports which force-kills any process listening on common ports
(7007,8080,8001,3030); change this to be opt-in or scope kills to only
Helios-owned processes: remove the unconditional dependency on dev:free-ports in
the dev:portal task and instead call it only when an env flag (e.g.
CLEAN_PORTS=true) is set, or update the dev:free-ports scripts to filter PIDs by
process command/owner (e.g. only kill processes whose command line or owner
matches Helios) before sending SIGKILL; update references to start-dev.sh /
start-portal.ps1 if they rely on the unconditional cleanup so they can opt in
via the env flag.

---

Outside diff comments:
In `@apps/operator/internal/controller/heliosapp_controller.go`:
- Around line 228-249: The SetupWithManager adds a watcher for tekton.dev/v1
PipelineRun (see pr variable and r.findObjectsForPipelineRun) but there is no
kubebuilder RBAC granting get,list,watch on pipelineruns; add a kubebuilder RBAC
comment for the PipelineRun resource with verbs=get;list;watch (matching
Group=tekton.dev Version=v1 Resource=pipelineruns) so the controller pod can
inform and reconcile PipelineRun events referenced by SetupWithManager/
findObjectsForPipelineRun.

In `@apps/operator/internal/controller/tekton/pipelinerun.go`:
- Around line 44-57: PipelineRun creation uses apiVersion "tekton.dev/v1beta1"
in pipelinerun.go but the reconciler (PrunePipelineRuns/CancelOlderPipelineRuns
in reconciler.go) lists PipelineRunList with
schema.GroupVersionKind{Group:"tekton.dev", Version:"v1"}, causing a mismatch;
update the GroupVersionKind used when listing PipelineRunList to
Version:"v1beta1" (or otherwise make both sides use the same Tekton API version)
so prune/cancel operate on the same resource version as created.

In `@cue/definitions/tekton/pipelines/patterns.cue`:
- Around line 247-256: The params array in patterns.cue uses uppercase names
"REPLICAS" and "PORT" which don't match the lowered param names used by the
git-update-manifest task (see git-update.cue); replace the two entries with
name: "replicas" and name: "port" (or whatever exact lowercase identifiers the
task defines) so the overrides from patterns.cue apply to the
git-update-manifest task results and prevent falling back to defaults 2/8080.

In `@Taskfile.yml`:
- Around line 593-600: The current patch command overwrites the default
ServiceAccount's imagePullSecrets array; change the logic that targets the
'default' ServiceAccount so it appends the docker-credentials entry only if
missing instead of replacing the whole array. Locate the kubectl patch for "sa
default" in the Taskfile.yml and replace the destructive patch with a safe
check-and-append approach (e.g., use a JSON patch via kubectl --type=json that
conditionally adds the {"name":"docker-credentials"} entry if not present, or
fetch the SA, inspect imagePullSecrets and patch/merge back only when needed) so
existing imagePullSecrets are preserved. Ensure the same non-destructive
behavior is applied consistently alongside the existing 'pipeline'
ServiceAccount handling.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 992f82c4-34ad-4e33-8cb1-5a443a15b418

📥 Commits

Reviewing files that changed from the base of the PR and between 8278027 and 0119292.

⛔ Files ignored due to path filters (6)
  • apps/operator/go.sum is excluded by !**/*.sum
  • apps/portal/.yarn/patches/@backstage-plugin-scaffolder-backend-module-gitea-npm-0.2.21-ac8e102ebc.patch is excluded by !**/.yarn/**
  • apps/portal/.yarn/releases/yarn-4.15.0.cjs is excluded by !**/.yarn/**
  • apps/portal/.yarn/releases/yarn-4.4.1.cjs is excluded by !**/.yarn/**
  • apps/portal/examples/nestjs-prisma-template/content/source/package-lock.json is excluded by !**/package-lock.json
  • apps/portal/yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (148)
  • .github/workflows/operator-ci.yml
  • .github/workflows/portal-ci.yml
  • .gitignore
  • Taskfile.yml
  • apps/operator/.github/workflows/lint.yml
  • apps/operator/.github/workflows/test-e2e.yml
  • apps/operator/.github/workflows/test.yml
  • apps/operator/.golangci.yml
  • apps/operator/AUTOMATION_GUIDE.md
  • apps/operator/Makefile
  • apps/operator/README.md
  • apps/operator/api/v1alpha1/groupversion_info.go
  • apps/operator/api/v1alpha1/heliosapp_types.go
  • apps/operator/cmd/main.go
  • apps/operator/config/crd/bases/app.helios.io_heliosapps.yaml
  • apps/operator/config/manager/kustomization.yaml
  • apps/operator/go.mod
  • apps/operator/internal/controller/argocd/application.go
  • apps/operator/internal/controller/argocd/application_test.go
  • apps/operator/internal/controller/database/credentials.go
  • apps/operator/internal/controller/database/injection.go
  • apps/operator/internal/controller/database/reconciler.go
  • apps/operator/internal/controller/database/reconciler_test.go
  • apps/operator/internal/controller/database/resources.go
  • apps/operator/internal/controller/database/resources_test.go
  • apps/operator/internal/controller/database/traits.go
  • apps/operator/internal/controller/gitopssync/reconciler.go
  • apps/operator/internal/controller/heliosapp_controller.go
  • apps/operator/internal/controller/heliosapp_controller_test.go
  • apps/operator/internal/controller/heliosapp_controller_unit_test.go
  • apps/operator/internal/controller/shared/gitea_url.go
  • apps/operator/internal/controller/tekton/pipelinerun.go
  • apps/operator/internal/controller/tekton/reconciler.go
  • apps/operator/internal/cue/e2e_validation_test.go
  • apps/operator/internal/cue/engine.go
  • apps/operator/internal/cue/engine_test.go
  • apps/operator/internal/cue/tekton.go
  • apps/operator/internal/cue/tekton_test.go
  • apps/operator/internal/gitops/gitops.go
  • apps/operator/internal/gitops/gitops_test.go
  • apps/operator/tekton/pipeline.yaml
  • apps/operator/test/e2e/e2e_suite_test.go
  • apps/operator/test/utils/utils.go
  • apps/portal/.gitignore
  • apps/portal/.yarnrc.yml
  • apps/portal/app-config.yaml
  • apps/portal/backstage.json
  • apps/portal/examples/advanced-template/template.yaml
  • apps/portal/examples/dotnet-template/content/README.md
  • apps/portal/examples/dotnet-template/content/gitops/helios-app.yaml
  • apps/portal/examples/dotnet-template/content/source/.env.example
  • apps/portal/examples/dotnet-template/content/source/Dockerfile
  • apps/portal/examples/dotnet-template/content/source/Program.cs
  • apps/portal/examples/dotnet-template/content/source/README.md
  • apps/portal/examples/dotnet-template/content/source/appsettings.json
  • apps/portal/examples/dotnet-template/content/source/docker-compose.yml
  • apps/portal/examples/dotnet-template/content/source/global.json
  • apps/portal/examples/dotnet-template/template.yaml
  • apps/portal/examples/nestjs-prisma-template/content/gitops/helios-app.yaml
  • apps/portal/examples/nestjs-prisma-template/content/source-db/prisma.config.ts
  • apps/portal/examples/nestjs-prisma-template/content/source-db/prisma/migrations/migration_lock.toml
  • apps/portal/examples/nestjs-prisma-template/content/source-db/prisma/schema.prisma
  • apps/portal/examples/nestjs-prisma-template/content/source-db/src/prisma/prisma.module.ts
  • apps/portal/examples/nestjs-prisma-template/content/source-db/src/prisma/prisma.service.ts
  • apps/portal/examples/nestjs-prisma-template/content/source/.dockerignore
  • apps/portal/examples/nestjs-prisma-template/content/source/.env.example
  • apps/portal/examples/nestjs-prisma-template/content/source/Dockerfile
  • apps/portal/examples/nestjs-prisma-template/content/source/README.md
  • apps/portal/examples/nestjs-prisma-template/content/source/package.json
  • apps/portal/examples/nestjs-prisma-template/content/source/src/app.module.ts
  • apps/portal/examples/nestjs-prisma-template/content/source/src/app.service.ts
  • apps/portal/examples/nestjs-prisma-template/content/source/tsconfig.json
  • apps/portal/examples/nestjs-prisma-template/template.yaml
  • apps/portal/examples/postgrest-template/template.yaml
  • apps/portal/examples/spring-boot-template/content/source/Dockerfile
  • apps/portal/examples/spring-boot-template/content/source/docker-compose.yml
  • apps/portal/examples/spring-boot-template/template.yaml
  • apps/portal/package.json
  • apps/portal/packages/app/e2e-tests/app.test.ts
  • apps/portal/packages/app/package.json
  • apps/portal/packages/app/public/index.html
  • apps/portal/packages/app/src/App.tsx
  • apps/portal/packages/app/src/apis.ts
  • apps/portal/packages/app/src/components/Root/LogoFull.tsx
  • apps/portal/packages/app/src/components/Root/LogoIcon.tsx
  • apps/portal/packages/app/src/components/database/DatabaseTab.tsx
  • apps/portal/packages/app/src/scaffolder/DatabasePickerExtension/DatabasePicker.tsx
  • apps/portal/packages/app/src/scaffolder/UniqueNamePickerExtension/UniqueNamePicker.tsx
  • apps/portal/packages/app/src/scaffolder/UniqueNamePickerExtension/extension.ts
  • apps/portal/packages/app/src/scaffolder/UniqueNamePickerExtension/index.ts
  • apps/portal/packages/app/src/scaffolder/index.ts
  • apps/portal/packages/app/src/themes/heliosThemes.ts
  • apps/portal/packages/backend/package.json
  • apps/portal/packages/backend/src/extensions/database-router-simple.ts
  • apps/portal/plugins/helios-backend/README.md
  • apps/portal/plugins/helios-backend/package.json
  • apps/portal/plugins/helios-backend/src/plugin.ts
  • apps/portal/plugins/helios-backend/src/router.ts
  • apps/portal/plugins/helios-backend/tsconfig.json
  • apps/portal/start-dev.sh
  • apps/portal/tsconfig.json
  • cue/cue.mod/module.cue
  • cue/definitions/bases/deployment.cue
  • cue/definitions/bases/service.cue
  • cue/definitions/components/web-service.cue
  • cue/definitions/tekton/common.cue
  • cue/definitions/tekton/pipelines/patterns.cue
  • cue/definitions/tekton/schema.cue
  • cue/definitions/tekton/tasks/buildah-build.cue
  • cue/definitions/tekton/tasks/git-clone.cue
  • cue/definitions/tekton/tasks/git-update.cue
  • cue/definitions/tekton/tasks/kaniko-build.cue
  • cue/definitions/tekton/tasks/postgrest-reload.cue
  • cue/definitions/tekton/tasks/registry.cue
  • cue/definitions/tekton/triggers/github-push.cue
  • cue/engine/builder.cue
  • cue/engine/tekton_builder.cue
  • docs/APP_STARTUP_GUIDE.md
  • docs/ARCHITECTURE.md
  • docs/design/tekton-cue-mapping-design.md
  • docs/design/tekton-cue-task-breakdown.md
  • infrastructure/environments/local-dev/.terraform.lock.hcl
  • infrastructure/environments/local-dev/main.tf
  • infrastructure/environments/local-dev/providers.tf
  • infrastructure/environments/local-dev/terraform.tfvars
  • infrastructure/environments/local-dev/variables.tf
  • infrastructure/environments/prod/.terraform.lock.hcl
  • infrastructure/environments/prod/main.tf
  • infrastructure/environments/prod/providers.tf
  • infrastructure/environments/prod/variables.tf
  • infrastructure/modules/cluster-k3d/main.tf
  • infrastructure/modules/cluster-k3d/registries.yaml.tpl
  • infrastructure/modules/cluster-k3d/variables.tf
  • infrastructure/modules/cluster-k3d/versions.tf
  • infrastructure/modules/git-auth/main.tf
  • infrastructure/modules/git-auth/variables.tf
  • infrastructure/modules/git-auth/versions.tf
  • infrastructure/modules/gitea/main.tf
  • infrastructure/modules/gitea/variables.tf
  • infrastructure/modules/gitea/versions.tf
  • infrastructure/modules/platform-services/argocd.tf
  • infrastructure/modules/platform-services/tekton.tf
  • infrastructure/modules/platform-services/variables.tf
  • infrastructure/modules/platform-services/versions.tf
  • scripts/check-prereqs.bat
  • scripts/check-prereqs.sh
  • scripts/setup-credentials.ps1
  • scripts/start-portal.ps1
💤 Files with no reviewable changes (2)
  • apps/portal/plugins/helios-backend/README.md
  • cue/definitions/tekton/tasks/kaniko-build.cue

Comment thread .github/workflows/operator-ci.yml
curl -Lo ./kind https://kind.sigs.k8s.io/dl/latest/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial | ⚡ Quick win

Cân nhắc ghim script cài đặt k3d theo tag phát hành thay vì nhánh main.

Tải script trực tiếp từ .../k3d/main/install.sh rồi | bash khiến build không tái lập được và dễ vỡ khi script thượng nguồn thay đổi. Nên trỏ tới một tag cố định (ví dụ TAG=vX.Y.Z) để ổn định và an toàn hơn.

♻️ Gợi ý ghim phiên bản
-      - name: Install the latest version of k3d
+      - name: Install a pinned version of k3d
         run: |
-          curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash
+          curl -s https://raw.githubusercontent.com/k3d-io/k3d/v5.7.4/install.sh | TAG=v5.7.4 bash
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/operator/.github/workflows/test-e2e.yml` at line 25, Thay vì tải script
cài đặt k3d từ nhánh main, sửa bước chạy curl để ghim một tag phát hành cố định
(ví dụ thiết lập TAG=vX.Y.Z và dùng
https://raw.githubusercontent.com/k3d-io/k3d/$TAG/install.sh) và chạy script đã
ghim, đảm bảo hành vi lặp lại; cập nhật dòng hiện tại chứa "curl -s
https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash" để sử dụng
biến TAG hoặc hằng số tag và (tùy chọn) thêm kiểm tra checksum/signature trước
khi pipe vào bash.

Comment thread apps/operator/.golangci.yml
ObjectMeta: metav1.ObjectMeta{Name: "api-server-db", Namespace: app.Namespace},
Spec: appsv1.StatefulSetSpec{
Replicas: func() *int32 { r := int32(1); return &r }(),
Replicas: func() *int32 { return new(int32(1)) }(),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Xác minh trong codebase còn pattern new(int32(...)) gây lỗi cú pháp hay không
rg -nP 'new\s*\(\s*int32\s*\(' --type go

Repository: helios-platform-team/helios-platform

Length of output: 293


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- resources.go (around line 110) ----"
nl -ba apps/operator/internal/controller/database/resources.go | sed -n '90,130p'

echo "---- reconciler_test.go (around line 348) ----"
nl -ba apps/operator/internal/controller/database/reconciler_test.go | sed -n '320,380p'

Repository: helios-platform-team/helios-platform

Length of output: 182


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "---- resources.go (around line 110) ----"
sed -n '95,125p' apps/operator/internal/controller/database/resources.go

echo "---- reconciler_test.go (around line 348) ----"
sed -n '330,370p' apps/operator/internal/controller/database/reconciler_test.go

Repository: helios-platform-team/helios-platform

Length of output: 2408


Sửa biểu thức khởi tạo con trỏ Replicas (new(int32(1))) vì không hợp lệ trong Go

  • Trong apps/operator/internal/controller/database/resources.goapps/operator/internal/controller/database/reconciler_test.go đang dùng Replicas: ... new(int32(1)), cú pháp này không hợp lệ (đối số của new phải là type, không phải giá trị/cast), sẽ làm fail compile.
  • Thay bằng cách tạo biến int32(1) rồi trả về địa chỉ.
💡 Đề xuất sửa
-			Replicas:    new(int32(1)),
+			Replicas: func() *int32 { v := int32(1); return &v }(),
-				Replicas: func() *int32 { return new(int32(1)) }(),
+				Replicas: func() *int32 { v := int32(1); return &v }(),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Replicas: func() *int32 { return new(int32(1)) }(),
Replicas: func() *int32 { v := int32(1); return &v }(),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/operator/internal/controller/database/reconciler_test.go` at line 348,
Trình biên dịch báo lỗi vì dùng new(int32(1)) (đối số của new phải là kiểu,
không phải giá trị); sửa tất cả chỗ sử dụng này (ví dụ trường Replicas trong
resources.go và reconciler_test.go) bằng cách khởi tạo một biến kiểu int32 với
giá trị 1 rồi trả về địa chỉ của biến đó (ví dụ: tạo biến v := int32(1) và trả
về &v trong biểu thức khởi tạo), hoặc dùng helper trả về *int32 nếu dự án có;
cập nhật mọi vị trí dùng new(int32(1)) thành mẫu khởi tạo
biến-and-return-address tương tự.

Comment on lines +224 to +228
// Sort oldest first
sort.Slice(prList.Items, func(i, j int) bool {
iTime := prList.Items[i].GetCreationTimestamp()
return iTime.Before(new(prList.Items[j].GetCreationTimestamp()))
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Xác nhận builtin `new` không bị shadow trong package và liệt kê mọi chỗ dùng new(...)
ast-grep --pattern 'func new($$$) { $$$ }'
rg -nP '\bnew\(' --type=go apps/operator/internal/controller/tekton

Repository: helios-platform-team/helios-platform

Length of output: 332


Sửa lỗi dùng new(...) với giá trị metav1.Time trong comparator sort (sẽ không biên dịch)

Trong Go, new nhận kiểu chứ không nhận biểu thức. Vì GetCreationTimestamp() trả về giá trị metav1.Time nên iTime.Before(new(...))jTime.Before(new(...)) sẽ lỗi biên dịch; Before cần *metav1.Time nên phải truyền &var.

🐛 Đề xuất sửa cho cả hai hàm
 	// Sort oldest first
 	sort.Slice(prList.Items, func(i, j int) bool {
-		iTime := prList.Items[i].GetCreationTimestamp()
-		return iTime.Before(new(prList.Items[j].GetCreationTimestamp()))
+		iTime := prList.Items[i].GetCreationTimestamp()
+		jTime := prList.Items[j].GetCreationTimestamp()
+		return iTime.Before(&jTime)
 	})
 	// Sort newest first (jTime before iTime means iTime is newer, so sorting newest first)
 	sort.Slice(prList.Items, func(i, j int) bool {
-		jTime := prList.Items[j].GetCreationTimestamp()
-		return jTime.Before(new(prList.Items[i].GetCreationTimestamp()))
+		iTime := prList.Items[i].GetCreationTimestamp()
+		jTime := prList.Items[j].GetCreationTimestamp()
+		return jTime.Before(&iTime)
 	})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/operator/internal/controller/tekton/reconciler.go` around lines 224 -
228, The comparator passed to sort.Slice is taking metav1.Time values and
incorrectly using new(...) which doesn't compile; fix the comparator in the
sort.Slice call by comparing the underlying time.Time values (e.g. use
prList.Items[i].GetCreationTimestamp().Time.Before(prList.Items[j].GetCreationTimestamp().Time))
or by taking addresses of named metav1.Time variables (jTime :=
prList.Items[j].GetCreationTimestamp(); iTime :=
prList.Items[i].GetCreationTimestamp(); return iTime.Before(&jTime)); update the
comparator in the sort.Slice (the anonymous func used to sort prList.Items)
accordingly.

Comment thread scripts/check-prereqs.bat
Comment on lines +38 to +41
call :check_tool "make" "make --version"
call :check_tool "operator-sdk" "operator-sdk version"
call :check_tool "terraform" "terraform version"
call :check_tool "task" "task --version"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

make nên là tool tùy chọn để đồng nhất với check-prereqs.sh.

Trong check-prereqs.sh, make được kiểm tra qua check_optional_tool (chỉ cảnh báo). Ở đây make dùng :check_tool nên khi thiếu sẽ tăng ERRORS và script thoát với mã lỗi (exit /b 1), chặn quá trình setup trên Windows một cách không nhất quán giữa hai nền tảng.

🔧 Đề xuất sửa
-call :check_tool "make" "make --version"
+call :check_optional_tool "make" "make --version"
 call :check_tool "operator-sdk" "operator-sdk version"
 call :check_tool "terraform" "terraform version"
 call :check_tool "task" "task --version"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
call :check_tool "make" "make --version"
call :check_tool "operator-sdk" "operator-sdk version"
call :check_tool "terraform" "terraform version"
call :check_tool "task" "task --version"
call :check_optional_tool "make" "make --version"
call :check_tool "operator-sdk" "operator-sdk version"
call :check_tool "terraform" "terraform version"
call :check_tool "task" "task --version"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/check-prereqs.bat` around lines 38 - 41, The call that enforces
`make` as required uses the required check routine `:check_tool` which makes
Windows fail hard; change the `call :check_tool "make" "make --version"`
invocation to use the optional routine `:check_optional_tool` so `make` is
treated as a warning (matching the behavior of check-prereqs.sh). Locate the
`call :check_tool "make" "make --version"` line and replace it with `call
:check_optional_tool "make" "make --version"` (leaving the other `:check_tool`
calls for operator-sdk, terraform, task unchanged).

Comment on lines +32 to +34
Write-Host "Patching default service account for image pull secrets..."
kubectl patch sa default -p '{"imagePullSecrets": [{"name": "docker-credentials"}]}'
Write-Host "Patched default service account with docker-credentials image pull secret"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Chỉ định rõ namespace khi patch ServiceAccount default.

kubectl patch sa default không có -n default sẽ patch theo namespace hiện tại của context, có thể không phải default, dẫn tới việc gán imagePullSecrets sai chỗ. (Bước patch pipeline ở Line 26 cũng đang thiếu namespace tương tự — nên cân nhắc đồng bộ.)

🛠️ Gợi ý sửa
 Write-Host "Patching default service account for image pull secrets..."
-kubectl patch sa default -p '{"imagePullSecrets": [{"name": "docker-credentials"}]}'
+kubectl patch sa default -n default -p '{"imagePullSecrets": [{"name": "docker-credentials"}]}'
 Write-Host "Patched default service account with docker-credentials image pull secret"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Write-Host "Patching default service account for image pull secrets..."
kubectl patch sa default -p '{"imagePullSecrets": [{"name": "docker-credentials"}]}'
Write-Host "Patched default service account with docker-credentials image pull secret"
Write-Host "Patching default service account for image pull secrets..."
kubectl patch sa default -n default -p '{"imagePullSecrets": [{"name": "docker-credentials"}]}'
Write-Host "Patched default service account with docker-credentials image pull secret"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/setup-credentials.ps1` around lines 32 - 34, The kubectl patch
command in the script (the block using "Write-Host" and "kubectl patch sa
default -p '{"imagePullSecrets": [{"name": "docker-credentials"}]}'") does not
specify a namespace and will operate against the current kubectl context; update
the patch command to include the namespace flag (e.g., add -n default) so the
default ServiceAccount in the intended namespace is patched, and likewise update
the earlier pipeline patch step that patches the ServiceAccount to also include
-n default to keep behavior consistent.

Comment thread scripts/start-portal.ps1
Write-Host "[ArgoCD] Fetching Admin Password..." -ForegroundColor Yellow
$passB64 = $adminSecret.data.password
$pass = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($passB64)).Trim()
Write-Host "[ArgoCD] Admin Password: $pass" -ForegroundColor Green
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Không in mật khẩu admin của ArgoCD ra console.

Việc ghi Admin Password: $pass ra console làm rò rỉ bí mật vào output/log của terminal (và có thể bị thu thập bởi log của CI/IDE). Mật khẩu đã được dùng ngay sau đó để sinh token nên không cần in ra. Nên loại bỏ, hoặc chỉ hướng dẫn cách lấy thủ công khi cần.

🔒 Gợi ý sửa
     $pass = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($passB64)).Trim()
-    Write-Host "[ArgoCD] Admin Password: $pass" -ForegroundColor Green
+    Write-Host "[ArgoCD] Admin password fetched successfully." -ForegroundColor Green
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Write-Host "[ArgoCD] Admin Password: $pass" -ForegroundColor Green
Write-Host "[ArgoCD] Admin password fetched successfully." -ForegroundColor Green
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/start-portal.ps1` at line 37, Remove the sensitive Write-Host call
that prints the ArgoCD admin password (the line containing Write-Host "[ArgoCD]
Admin Password: $pass") so the secret is not emitted to console/logs; instead
either omit any output or replace it with a non-sensitive informational message
(e.g., "ArgoCD admin password generated — handle securely" or instructions on
how to retrieve the password manually) since the password is immediately used to
generate a token and should not be logged.

Comment thread Taskfile.yml
Comment on lines +123 to +179
setup:all:
desc: Run full setup sequence (registry + infra + tekton + portal deps)
cmds:
- task: setup:registry
- task: setup:terraform
- task: setup:tekton
- task: setup:portal-deps

setup:registry:
desc: Create a persistent local pull-through cache registry (survives task clean)
cmds:
- cmd: |
REGISTRY_NAME="{{.REGISTRY_NAME}}"
REGISTRY_PORT="{{.REGISTRY_PORT}}"

if k3d registry list "k3d-${REGISTRY_NAME}" > /dev/null 2>&1; then
echo "Registry 'k3d-${REGISTRY_NAME}' already exists on port ${REGISTRY_PORT}. Skipping."
else
echo "Creating local pull-through cache registry 'k3d-${REGISTRY_NAME}' on port ${REGISTRY_PORT}..."
k3d registry create "${REGISTRY_NAME}" \
--port "${REGISTRY_PORT}" \
--proxy-remote-url "https://registry-1.docker.io" \
--proxy-username "${DOCKER_USERNAME:-}" \
--proxy-password "${DOCKER_TOKEN:-}"
echo "Registry created. Docker Hub pulls will now be cached locally."
fi
platforms: [linux, darwin]

setup:terraform:
desc: Bootstrap the local environment (cluster + apps) using Terraform
dir: infrastructure/environments/local-dev
cmds:
- |
echo "Ensuring k3d cluster '{{.CLUSTER_NAME}}' exists..."
mkdir -p ~/.kube
touch ~/.kube/config
if ! k3d cluster list {{.CLUSTER_NAME}} > /dev/null 2>&1; then
echo "Creating k3d cluster '{{.CLUSTER_NAME}}'..."
# Render the registry mirror config from the committed template
mkdir -p ~/.k3d
sed \
-e "s/REGISTRY_NAME/{{.REGISTRY_NAME}}/g" \
-e "s/REGISTRY_PORT/{{.REGISTRY_PORT}}/g" \
"$(pwd)/../../modules/cluster-k3d/registries.yaml.tpl" \
> ~/.k3d/helios-registries.yaml
k3d cluster create {{.CLUSTER_NAME}} \
--image rancher/k3s:v1.36.1-k3s1 \
--agents 1 \
--wait \
--api-port 127.0.0.1:6550 \
--k3s-arg "--disable=traefik@server:0" \
--k3s-arg "--disable=metrics-server@server:0" \
--registry-use "k3d-{{.REGISTRY_NAME}}:{{.REGISTRY_PORT}}" \
--registry-config ~/.k3d/helios-registries.yaml
fi
echo "Merging kubeconfig context..."
k3d kubeconfig merge {{.CLUSTER_NAME}} -d -s > /dev/null 2>&1 || true
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

task setup hiện không còn chạy được trên Windows như phần đầu file mô tả.

setup:all gọi thẳng setup:registry, nhưng task đó chỉ có linux/darwin; setup:terraform cũng là shell POSIX thuần. Trên Windows, luồng bootstrap mới sẽ dừng trước khi dựng môi trường xong. Nên tách nhánh theo platform hoặc fail-fast với thông báo rõ là chỉ hỗ trợ WSL/Git Bash cho toàn bộ luồng setup.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Taskfile.yml` around lines 123 - 179, The Taskfile's setup flow (setup:all ->
setup:registry and setup:terraform) assumes POSIX shells and currently skips
setup:registry on Windows (platforms: [linux, darwin]) which breaks bootstrap on
Windows; update Taskfile.yml so setup:all either branches by platform or fails
fast with a clear message. Concretely, modify setup:all to detect platform and:
(a) call the existing setup:registry and setup:terraform on linux/darwin, or (b)
when on Windows, print an explicit error and exit recommending WSL/Git Bash (or
invoke Windows-compatible equivalents) — touch the tasks named setup:all,
setup:registry and setup:terraform to add the platform-check/fail-fast logic and
messages so the bootstrap won't silently stop on native Windows shells.

Comment thread Taskfile.yml
Comment on lines 628 to +666
dev:portal:
desc: Run the Backstage portal with ArgoCD + kubectl proxy
dir: apps/portal
cmds:
- task: dev:free-ports
- cmd: ./start-dev.sh
platforms: [linux, darwin]
- cmd: powershell -ExecutionPolicy Bypass -File ../../scripts/start-portal.ps1 -ArgocdPort {{.ARGOCD_PORT}}
platforms: [windows]

dev:free-ports:
desc: Ensure common dev ports are free (override with PORTS=7007,8080,...)
cmds:
- cmd: |
PORTS_RAW="{{.PORTS}}"
if [ -z "$PORTS_RAW" ]; then
PORTS_RAW="7007,8080,8001,3030"
fi

if ! command -v lsof >/dev/null 2>&1; then
echo "lsof not found; skipping port cleanup on linux/darwin."
exit 0
fi

PORTS=$(echo "$PORTS_RAW" | tr ',' ' ')
for PORT in $PORTS; do
PIDS="$(lsof -t -iTCP:${PORT} -sTCP:LISTEN || true)"
if [ -n "$PIDS" ]; then
echo "Port ${PORT} busy. Stopping process(es): $PIDS"
for PID in $PIDS; do
/bin/kill -9 "$PID" 2>/dev/null || command kill -9 "$PID" 2>/dev/null || true
done
fi
done
sleep 1
platforms: [linux, darwin]
- cmd: |
powershell -ExecutionPolicy Bypass -Command "$portsRaw='{{.PORTS}}'; if ([string]::IsNullOrWhiteSpace($portsRaw)) { $portsRaw='7007,8080,8001,3030' }; $ports = $portsRaw -split '[,\s]+' | Where-Object { $_ -ne '' }; foreach ($port in $ports) { $connections = Get-NetTCPConnection -LocalPort ([int]$port) -State Listen -ErrorAction SilentlyContinue; if ($connections) { $pids = $connections | Select-Object -ExpandProperty OwningProcess -Unique; Write-Host ('Port ' + $port + ' busy. Stopping process(es): ' + ($pids -join ', ')); foreach ($pid in $pids) { Stop-Process -Id $pid -Force -ErrorAction SilentlyContinue } } }"
platforms: [windows]
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

dev:portal đang kill mọi process nghe trên các port phổ biến mà không kiểm tra nguồn gốc.

dev:portal luôn gọi dev:free-ports, chạy task này sẽ cưỡng bức dừng bất kỳ service nào đang dùng 7007/8080/8001/3030, kể cả service không thuộc repo. Ít nhất nên biến bước này thành opt-in, hoặc chỉ dọn các PID do Helios khởi chạy.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Taskfile.yml` around lines 628 - 666, The dev:portal task currently always
invokes dev:free-ports which force-kills any process listening on common ports
(7007,8080,8001,3030); change this to be opt-in or scope kills to only
Helios-owned processes: remove the unconditional dependency on dev:free-ports in
the dev:portal task and instead call it only when an env flag (e.g.
CLEAN_PORTS=true) is set, or update the dev:free-ports scripts to filter PIDs by
process command/owner (e.g. only kill processes whose command line or owner
matches Helios) before sending SIGKILL; update references to start-dev.sh /
start-portal.ps1 if they rely on the unconditional cleanup so they can opt in
via the env flag.

@PhuocHoan PhuocHoan linked an issue May 31, 2026 that may be closed by this pull request
3 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Terraform-based "App of Apps" Pattern for Local and Prod Environments

2 participants